package andev.game2048;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.GridLayout;

import java.util.ArrayList;
import java.util.Random;

import andev.game2048.Card.Card;

/**
 * Created by lzy1g on 2015/8/6.
 */
public class GameView extends GridLayout implements DialogInterface.OnClickListener {
    public static int cardWidth;
    public static ArrayList<Card> emptyCardList = new ArrayList<>();
    private final int TRANS = 1;//TRANS 代表数字>0的卡片移动到一个空白的卡片上
    private final int FUSE = 2;//FUSE 代表数字相同(不为0)的卡片融合
    private int bkgColor = Color.parseColor("#9EAFB8");
    private Card[][] cards = new Card[4][4];
    private int margin, padding;
    private GestureDetector gestureDetector;

    public GameView(Context context) {
        this(context, null);
    }

    public GameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        gestureDetector = new GestureDetector(context, new GameViewListener(this));

        setBackgroundColor(bkgColor);

        padding = margin = (int) MainActivity.mainActivity.dpToPixel(5);

        cardWidth = (Math.min(MainActivity.mainActivity.getScreenSize().x, MainActivity.mainActivity.getScreenSize().y) - 8 * margin - 2 * padding) / 4;

        setPadding(padding, padding, padding, padding);

        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 4; j++) {
                Card card = new Card(context);
                emptyCardList.add(card);
                cards[i][j] = card;
                card.row = i;
                card.col = j;

                GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams();
                layoutParams.setMargins(margin, margin, margin, margin);
                layoutParams.width = layoutParams.height = cardWidth;
                addView(card, layoutParams);
            }
        }

        restartGame();
    }

    private void restartGame() {
        GameView.emptyCardList.clear();

        for (int i = 0; i < 4; i++)
            for (int j = 0; j < 4; j++)
                cards[i][j].setNumber(0, null);

        generateNumber();
        generateNumber();
    }

    private void generateNumber() {
        //before generating,if empty card is 0,then return
        int size = emptyCardList.size();
        if (size == 0) return;
        Random random = new Random();
        int pos = random.nextInt(size);

        boolean is4 = 0.9 < random.nextFloat();
        if (is4)
            emptyCardList.get(pos).setNumber(4, null);
        else
            emptyCardList.get(pos).setNumber(2, null);

        //after generated,if empty card is 0,then judge game
        if (emptyCardList.size() == 0) endGame(false);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return gestureDetector.onTouchEvent(event);
    }

    /**
     * @param bTrueSwipe 指定是否为玩家实际操作
     * @return true表明可以向右移动Cards
     */
    public boolean swipeRight(boolean bTrueSwipe) {
        boolean bGenerate = false;
        for (int i = 0; i < 4; i++) {
            for (int j1 = 3; j1 > 0; j1--) {
                Card selfCard = cards[i][j1];
                for (int j2 = j1 - 1; j2 > -1; j2--) {
                    Card otherCard = cards[i][j2];
                    int judgeResult = cardJudge(selfCard, otherCard, bTrueSwipe);
                    if (judgeResult == 0 && otherCard.getNumber() != 0) break;
                    if (judgeResult > 0)//当结果为FUSE或者TRANS，则bGenerate应该为true
                    {
                        bGenerate = true;
                        if (judgeResult == FUSE) break;
                    }
                }
            }
        }

        if (bGenerate) {
            if (bTrueSwipe) generateNumber();//排除计算机进行伪操作导致的bGenerate
            return true;
        }
        return false;
    }

    public boolean swipeLeft(boolean bTrueSwipe) {
        boolean bGenerate = false;
        for (int i = 0; i < 4; i++) {
            for (int j1 = 0; j1 < 3; j1++) {
                Card selfCard = cards[i][j1];
                for (int j2 = j1 + 1; j2 < 4; j2++) {
                    Card otherCard = cards[i][j2];
                    int judgeResult = cardJudge(selfCard, otherCard, bTrueSwipe);
                    if (judgeResult == 0 && otherCard.getNumber() != 0) break;
                    if (judgeResult > 0) {
                        bGenerate = true;
                        if (judgeResult == FUSE) break;
                    }
                }
            }
        }

        if (bGenerate) {
            if (bTrueSwipe) generateNumber();
            return true;
        }
        return false;
    }

    public boolean swipeDown(boolean bTrueSwipe) {
        boolean bGenerate = false;
        for (int j = 0; j < 4; j++) {
            for (int i1 = 3; i1 > 0; i1--) {
                Card selfCard = cards[i1][j];
                for (int i2 = i1 - 1; i2 > -1; i2--) {
                    Card otherCard = cards[i2][j];
                    int judgeResult = cardJudge(selfCard, otherCard, bTrueSwipe);
                    if (judgeResult == 0 && otherCard.getNumber() != 0) break;
                    if (judgeResult > 0) {
                        bGenerate = true;
                        if (judgeResult == FUSE) break;
                    }
                }
            }
        }
        if (bGenerate) {
            if (bTrueSwipe) generateNumber();
            return true;
        }
        return false;
    }

    public boolean swipeUp(boolean bTrueSwipe) {
        boolean bGenerate = false;
        for (int j = 0; j < 4; j++) {
            for (int i1 = 0; i1 < 3; i1++) {
                Card selfCard = cards[i1][j];
                for (int i2 = i1 + 1; i2 < 4; i2++) {
                    Card otherCard = cards[i2][j];
                    int judgeResult = cardJudge(selfCard, otherCard, bTrueSwipe);
                    if (judgeResult == 0 && otherCard.getNumber() != 0) break;
                    if (judgeResult > 0) {
                        bGenerate = true;
                        if (judgeResult == FUSE) break;
                    }
                }
            }
        }
        if (bGenerate) {
            if (bTrueSwipe) generateNumber();
            return true;
        }
        return false;
    }

    /**
     * @param card
     * @return 一个与指定Card一模一样的Card
     */
    private Card makeCloneCard(Card card) {
        Card cloneCard = new Card(getContext());
        cloneCard.setNumber(card.getNumber(), cloneCard);

        LayoutParams layoutParams = new LayoutParams();
        layoutParams.rowSpec = GridLayout.spec(card.row);
        layoutParams.columnSpec = GridLayout.spec(card.col);
        layoutParams.width = layoutParams.height = cardWidth;
        layoutParams.setMargins(margin, margin, margin, margin);

        addView(cloneCard, new LayoutParams(layoutParams));
        return cloneCard;
    }

    /**
     * @param selfCard
     * @param otherCard
     * @param bTrueSwipe 指定是否为玩家实际操作，如果true，将会执行对卡片的完全操作
     * @return 卡片是移动、融合还是无法移动
     */
    private int cardJudge(Card selfCard, Card otherCard, boolean bTrueSwipe) {
        int judgeResult = 0;
        int selfNumber = selfCard.getNumber(), otherNumber = otherCard.getNumber();

        if (selfNumber != 0) {
            if (otherNumber == selfNumber) {
                if (!bTrueSwipe) return FUSE;
                int newSelfNumber = selfNumber * 2;
                if (newSelfNumber == 2048) endGame(true);
                selfCard.setNumber(newSelfNumber, makeCloneCard(otherCard));
                otherCard.setNumber(0, null);
                judgeResult = FUSE;
            }
        } else {
            if (otherNumber != 0) {
                if (!bTrueSwipe) return TRANS;
                selfCard.setNumber(otherNumber, makeCloneCard(otherCard));
                otherCard.setNumber(0, null);
                judgeResult = TRANS;
            }
        }

        return judgeResult;
    }

    /**
     * @param bWin 指定胜负
     */
    public void endGame(boolean bWin) {
        AlertDialog.Builder ab = new AlertDialog.Builder(getContext())
                .setTitle("提示")
                .setPositiveButton("确定", this)
                .setNegativeButton("取消", this)
                .setCancelable(false);
        if (bWin) {
            ab.setMessage("你赢了").show();
        } else if (!swipeRight(false) && !swipeLeft(false) && !swipeUp(false) && !swipeDown(false)) {
            ab.setMessage("你输了").show();
        }
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case DialogInterface.BUTTON_POSITIVE:
                restartGame();
                break;
            case DialogInterface.BUTTON_NEGATIVE:
                break;
        }
    }
}
